#ifndef CODEC_CTX_H_
#define CODEC_CTX_H_ 1
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavutil/pixdesc.h>
#include <libswscale/swscale.h>
#include <libavutil/log.h>
}
#include <thread>
#include <vector>
#include <condition_variable>
#include <atomic>
#include "ring_queue.h"

struct codec_context
{
  AVCodec *codec_ = NULL;
  AVCodecParserContext *parser_ = NULL;
  AVCodecContext *c_ = NULL;
  AVFrame *frame_ = NULL;
  AVFrame *render_frame_ = NULL;
  AVPacket *pkt_ = NULL;
  SwsContext *sws_ctx_ = NULL;
  bool valid_ = false;
  std::vector<uint8_t> render_buffer_;
  int frame_cnt = 0;
  FILE *fp = NULL;
  Ring_Queue *iq = NULL, *oq = NULL;
  std::condition_variable cv_;
  std::mutex cv_mu_;
  bool quit_ = false;
  std::atomic<int> current_frame_cnt_;
  std::thread decoder_thread_;
  static constexpr int sem_count = 10;

  codec_context();

  ~codec_context();

  bool create_sws_ctx(int width, int height, AVPixelFormat src_fmt);
  // to rgb 24
  inline void convert()
  {
    sws_scale(sws_ctx_, frame_->data, frame_->linesize, 0, frame_->height, render_frame_->data, render_frame_->linesize);
  }
  // ����
  bool create(bool enable_asyn = true);
  void decode_thread_loop();
  int commit_packet(uint8_t *data, int len);
  std::vector<uint8_t> get_last_decoded_frame();
  int decode_frames(uint8_t *data, int len, std::vector<std::vector<uint8_t>> &res);
};

#endif
